{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Encode:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Generate random binary file"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Read binary file"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 海明码\n",
    "### 使用 hammingEncode()来编码\n",
    "### 使用 hammingDecode()来纠错\n",
    "### r  dataLen HammingLen是全局变量，调用chooseHammingN（）选择\n",
    "### 编码的位数n，改变r  dataLen HammingLen"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "metadata": {},
   "outputs": [],
   "source": [
    "r=0\n",
    "dataLen=0\n",
    "HammingLen=0\n",
    "def chooseHammingN(n):\n",
    "    global r\n",
    "    global dataLen\n",
    "    global HammingLen\n",
    "    dataLen = n\n",
    "    r = 0\n",
    "    while pow(2,r) - r < dataLen + 1:\n",
    "        r += 1\n",
    "    HammingLen = r + dataLen #求出插入校验码后的总长\n",
    "\n",
    "def hammingEncode(data):\n",
    "    global r\n",
    "    global dataLen\n",
    "    global HammingLen\n",
    "    HammingData = [1] * HammingLen\n",
    "    for i in range(r):\n",
    "        HammingData[pow(2,i)-1] = 0#先默认校验位都设置为0\n",
    "    dataIndex = 0\n",
    "    for i in range(HammingLen):#插入数据\n",
    "        if HammingData[i] == 1:\n",
    "            HammingData[i] = data[dataIndex]\n",
    "            dataIndex += 1\n",
    "            \n",
    "    for i in range(1,r+1):#逐个计算校验位\n",
    "        #pn所在位置\n",
    "        pos = pow(2,(i-1)) - 1\n",
    "        Pn = 0\n",
    "        for j in range(1,HammingLen+1):\n",
    "            if j & (2 ** (i-1)) == (2 ** (i-1)):\n",
    "                Pn ^= HammingData[j-1]\n",
    "        HammingData[pos] = Pn\n",
    "    return HammingData\n",
    "\n",
    "\n",
    "def binary_to_decimal(binary):\n",
    "    \"\"\"\n",
    "    Converts a binary number to decimal.\n",
    "    \"\"\"\n",
    "    decimal = 0\n",
    "    for digit in binary:\n",
    "        decimal = decimal*2 + int(digit)\n",
    "    return decimal\n",
    "\n",
    "def list_to_str(lst):\n",
    "    \"\"\"\n",
    "    Converts a list to a string.\n",
    "    \"\"\"\n",
    "    return ''.join(map(str, lst))\n",
    "\n",
    "def str_to_int_list(s):\n",
    "    \"\"\"\n",
    "    Converts a string to a list of integers.\n",
    "    \"\"\"\n",
    "    return [int(c) for c in s]\n",
    "\n",
    "def hammingDecode(HammingData_):\n",
    "    global r\n",
    "    global dataLen\n",
    "    global HammingLen\n",
    "    HammingData = HammingData_.copy()\n",
    "    G = [0]*(HammingLen-dataLen)\n",
    "    for i in range(1,r+1):#逐个计算校验位\n",
    "        #pn所在位置\n",
    "        pos = pow(2,(i-1)) - 1\n",
    "        Gn = 0\n",
    "        #print('参与异或的Hi：',i,'组')\n",
    "        for j in range(1,HammingLen+1):\n",
    "            if j & (2 ** (i-1)) == (2 ** (i-1)):\n",
    "                #print(j)\n",
    "                Gn ^= HammingData[j-1]\n",
    "        print('G',i,':',HammingData[pos])\n",
    "\n",
    "        if Gn == 1:\n",
    "            G[i-1] = 1\n",
    "            #wrongList.append(i)#记下哪个校验组错了\n",
    "    G = G[::-1]\n",
    "    decimal_G = binary_to_decimal(list_to_str(G))\n",
    "    print('list_to_str(G):',list_to_str(G))\n",
    "    print('decimal_G:',decimal_G)\n",
    "    HammingData[decimal_G-1] ^= 1  \n",
    "    return HammingData\n",
    "\n",
    "\n",
    "def extractData(encoded):\n",
    "    chouQv = []\n",
    "    for i in range(len(encoded)):\n",
    "        skip = False\n",
    "        for j in range(5):\n",
    "            if 2**j >len(encoded):\n",
    "                continue\n",
    "            if 2**j-1 == i:\n",
    "                skip = True\n",
    "        if not skip:\n",
    "            chouQv.append(encoded[i])\n",
    "    return chouQv\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 测试海明码"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "len a: 8\n",
      "a:\n",
      "10010111\n",
      "[1, 0, 0, 1, 0, 1, 1, 1]\n",
      "HammingLen: 12\n",
      "encoded:\n",
      "[1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1]\n",
      "101000110111\n",
      "extractData:\n",
      "[1, 0, 0, 1, 0, 1, 1, 1]\n",
      "----------------------------------------\n",
      "encoded:\n",
      "[1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1]\n",
      "pos  0  disturbed:\n",
      "[0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1]\n",
      "G 1 : 0\n",
      "G 2 : 0\n",
      "G 3 : 0\n",
      "G 4 : 1\n",
      "list_to_str(G): 0001\n",
      "decimal_G: 1\n",
      "decoded:\n",
      "[1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1]\n",
      "---------------------------------\n",
      "encoded:\n",
      "[1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1]\n",
      "pos  1  disturbed:\n",
      "[1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1]\n",
      "G 1 : 1\n",
      "G 2 : 1\n",
      "G 3 : 0\n",
      "G 4 : 1\n",
      "list_to_str(G): 0010\n",
      "decimal_G: 2\n",
      "decoded:\n",
      "[1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1]\n",
      "---------------------------------\n",
      "encoded:\n",
      "[1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1]\n",
      "pos  2  disturbed:\n",
      "[1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1]\n",
      "G 1 : 1\n",
      "G 2 : 0\n",
      "G 3 : 0\n",
      "G 4 : 1\n",
      "list_to_str(G): 0011\n",
      "decimal_G: 3\n",
      "decoded:\n",
      "[1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1]\n",
      "---------------------------------\n",
      "encoded:\n",
      "[1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1]\n",
      "pos  3  disturbed:\n",
      "[1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1]\n",
      "G 1 : 1\n",
      "G 2 : 0\n",
      "G 3 : 1\n",
      "G 4 : 1\n",
      "list_to_str(G): 0100\n",
      "decimal_G: 4\n",
      "decoded:\n",
      "[1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1]\n",
      "---------------------------------\n",
      "encoded:\n",
      "[1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1]\n",
      "pos  4  disturbed:\n",
      "[1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1]\n",
      "G 1 : 1\n",
      "G 2 : 0\n",
      "G 3 : 0\n",
      "G 4 : 1\n",
      "list_to_str(G): 0101\n",
      "decimal_G: 5\n",
      "decoded:\n",
      "[1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1]\n",
      "---------------------------------\n",
      "encoded:\n",
      "[1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1]\n",
      "pos  5  disturbed:\n",
      "[1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1]\n",
      "G 1 : 1\n",
      "G 2 : 0\n",
      "G 3 : 0\n",
      "G 4 : 1\n",
      "list_to_str(G): 0110\n",
      "decimal_G: 6\n",
      "decoded:\n",
      "[1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1]\n",
      "---------------------------------\n",
      "encoded:\n",
      "[1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1]\n",
      "pos  6  disturbed:\n",
      "[1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1]\n",
      "G 1 : 1\n",
      "G 2 : 0\n",
      "G 3 : 0\n",
      "G 4 : 1\n",
      "list_to_str(G): 0111\n",
      "decimal_G: 7\n",
      "decoded:\n",
      "[1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1]\n",
      "---------------------------------\n",
      "encoded:\n",
      "[1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1]\n",
      "pos  7  disturbed:\n",
      "[1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1]\n",
      "G 1 : 1\n",
      "G 2 : 0\n",
      "G 3 : 0\n",
      "G 4 : 0\n",
      "list_to_str(G): 1000\n",
      "decimal_G: 8\n",
      "decoded:\n",
      "[1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1]\n",
      "---------------------------------\n"
     ]
    }
   ],
   "source": [
    "\n",
    "\n",
    "a = [1, 0, 0, 1, 0, 1, 1, 1]\n",
    "print('len a:',len(a))\n",
    "print('a:')\n",
    "print(list_to_str(a))\n",
    "print(a)\n",
    "chooseHammingN(len(a))\n",
    "print('HammingLen:',HammingLen)\n",
    "\n",
    "encoded = hammingEncode(a)\n",
    "print('encoded:')\n",
    "print(encoded)\n",
    "print(list_to_str(encoded))\n",
    "\n",
    "print('extractData:')\n",
    "print(extractData(encoded))\n",
    "print('----------------------------------------')\n",
    "\n",
    "\n",
    "def check(encoded,decoded):\n",
    "    for i in range(len(encoded)):\n",
    "        if encoded[i]!=decoded[i]:\n",
    "            print('pos ',i,\" error\")\n",
    "    \n",
    "for i in range(len(a)):\n",
    "    print('encoded:')\n",
    "    print(encoded)\n",
    "    disturbed = encoded.copy()\n",
    "    disturbed[i] ^= 1\n",
    "    print('pos ',i,' disturbed:')\n",
    "    print(disturbed)\n",
    "    decoded = hammingDecode(disturbed)\n",
    "    print('decoded:')\n",
    "    print(decoded)\n",
    "    check(encoded,decoded)\n",
    "    print('---------------------------------')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Self-designed encode "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 用 自己写的encode（或qrcode 直接）生成二维码\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### About qrcode settings:\n",
    "1. version: int，range from 1 to 40  \n",
    "    * 表示二维码的大小（最小值是1，是个12×12的矩阵），如果想让程序自动生成，将值设置为 None 并使用 fit=True 参数即可\n",
    "2. error_correction: 二维码的纠错范围\n",
    "    * ERROR_CORRECT_L 7%以下的错误会被纠正\n",
    "    * ERROR_CORRECT_M (default) 15%以下的错误会被纠正\n",
    "    * ERROR_CORRECT_Q 25 %以下的错误会被纠正\n",
    "    * ERROR_CORRECT_H. 30%以下的错误会被纠正\n",
    "3. boxsize: 每个点（方块）中的像素个数\n",
    "4. border: 二维码距图像外围边框距离，默认为4，而且相关规定最小为4\n",
    "\n",
    "reference: https://pypi.org/project/qrcode/"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## pics to video\n",
    "### Use the VideoWriter():  \n",
    "VideoWriter(const String &filename, int fourcc, double fps, Size frameSize, bool isColor=true)\n",
    "* filename：需要生成的视频的名字\n",
    "* fourcc：用于压缩框架的解码器的4位编码(four code of codec)，你在这个链接里可以查找到可用的4位码（http://www.fourcc.org/codecs.php）\n",
    "* fps：每秒的视频帧数(framrate persecond)\n",
    "* frameSize：视频画面的尺寸（这里需要与用于合成视频的图片尺寸一致）\n",
    "* isColor：如果该位值为Ture，解码器会进行颜色框架的解码，否则会使用灰度进行颜色架构 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
